#include <rtthread.h>
#include <rtdevice.h>

#include <dfs_posix.h>
#include <dfs_poll.h>

#include "videolib.h"

static int _fops_open(struct dfs_fd *file, ...)
{
    int ret;
    rt_video_t *vid = (rt_video_t*)file->data;

    ret = rt_video_open(vid);

    return ret;
}

static int _fops_close(struct dfs_fd *file)
{
    int ret;
    rt_video_t *vid = (rt_video_t*)file->data;

    ret = rt_video_close(vid);

    return ret;
}

static int _fops_ioctl(struct dfs_fd *fd, int cmd, void *args)
{
    int ret = -EINVAL;
    rt_video_t *vid = (rt_video_t *)fd->data;

    switch (cmd)
    {
    case VIDIOC_S_FMT:
    {
        ret = rt_video_s_fmt(vid, (struct video_format*)args);
    }break;
    case VIDIOC_REQBUFS:
    {
        ret = rt_video_reqbufs(vid, (struct video_requestbuffers*)args);
    }break;
    case VIDIOC_QUERYBUF:
    {
        ret = rt_video_querybuf(vid, (struct video_buffer*)args);
    }break;
    case VIDIOC_QBUF:
    {
        ret = rt_video_qbuf(vid, (struct video_buffer*)args);
    }break;
    case VIDIOC_STREAMON:
    {
        ret = rt_video_streamon(vid);
    }break;
    }

    return ret;
}

static int _fops_read(struct dfs_fd *file, void *buf, size_t count, ...)
{
    int ret;
    rt_video_t *vid = (rt_video_t*)file->data;

    ret = rt_video_read(vid, buf, count, file->flags & O_NONBLOCK);

    return ret;
}

const static struct dfs_file_ops _vid_fops =
{
    _fops_open,
    RT_NULL,
    _fops_ioctl,
    _fops_read,
    RT_NULL,
    RT_NULL, /* flush */
    RT_NULL, /* lseek */
    RT_NULL, /* getdents */
    RT_NULL,
};

int rt_video_register(rt_video_t *vid, const char *name, void *userdata)
{
    int ret;

    vid->parent.user_data = userdata;

    ret = rt_device_register(&vid->parent, name, 0);

    vid->parent.fops = &_vid_fops;

    return ret;
}
